#include "videodiscover.h"

VideoDiscover::VideoDiscover(QObject *parent) : QThread(parent)
{
    m_timeout = 7000;  //每次探测最大时长
    m_interval = 5000; //每轮探测间隔
    m_stopReq = false;
}

VideoDiscover::~VideoDiscover()
{
    stopDiscover(true);

}
void VideoDiscover::addMedia(const MediaInfo &media)
{
    if(!containId(media.id)){
        m_mediasMutex.lock();
        m_medias.push_back(media);
        m_mediasMutex.unlock();
    }
    m_newMediaCond.wakeAll();
}

void VideoDiscover::removeMedia(const QString &mediaId)
{
    m_mediasMutex.lock();
    for(int i=m_medias.size()-1;i>=0;i--){
        if(m_medias[i].id == mediaId){
            m_medias.remove(i);
        }
    }
    m_mediasMutex.unlock();
}

bool VideoDiscover::containId(const QString &mediaId)
{
    bool contain=false;

    m_mediasMutex.lock();
    for(int i=0;i<m_medias.size();i++){
        if(m_medias[i].id == mediaId){
            contain = true;
            break;
        }
    }
    m_mediasMutex.unlock();

    return contain;
}

bool VideoDiscover::containUrl(const QString &mediaUrl)
{
    bool contain=false;

    m_mediasMutex.lock();
    for(int i=0;i<m_medias.size();i++){
        if(m_medias[i].url == mediaUrl){
            contain = true;
            break;
        }
    }
    m_mediasMutex.unlock();

    return contain;
}

void VideoDiscover::startDiscover()
{
    m_stopReq = false;
    this->start();
}

void VideoDiscover::stopDiscover(bool wait)
{
    m_stopReq = true;
    m_newMediaCond.wakeAll();
    m_resumeCond.wakeAll();
    if(wait){
        if(!this->wait(1000)){
            this->terminate();
        }
    }
}

int VideoDiscover::timeout()
{
    return m_timeout;
}

void VideoDiscover::setTimeout(int msec)
{
    m_timeout = msec;
}

int VideoDiscover::interval()
{
    return m_interval;
}

void VideoDiscover::setInterval(int msec)
{
    m_interval = msec;
}

void VideoDiscover::run()
{
    bool result =false;
    int curIndex=-1;

    while (1){
        if(m_medias.isEmpty()){
            m_newMediaMutex.lock();
            m_newMediaCond.wait(&m_newMediaMutex);
            m_newMediaMutex.unlock();
        }
        if(m_stopReq){
            break;
        }

        m_mediasMutex.lock();
        curIndex+=1;
        if(curIndex<0 || curIndex>=m_medias.size()){
            curIndex=0;
        }
        MediaInfo media = m_medias[curIndex];
        m_mediasMutex.unlock();

        if(curIndex==0){
            //每轮探测需要间隔m_interval毫秒
            m_resumeMutex.lock();
            m_resumeCond.wait(&m_resumeMutex,m_interval);
            m_resumeMutex.unlock();
        }

        if(m_stopReq){
            break;
        }

        //FIXME: 线程退出时，极限情况下会被阻塞m_timeout毫秒，可以考虑
        //改为调用gst_discoverer_discover_uri_async异步执行
        result=false;
        GError *err = NULL;
        GstDiscoverer *dc = gst_discoverer_new(m_timeout*GST_MSECOND, &err);
        GError *err2 = NULL;
        GstDiscovererInfo *info = gst_discoverer_discover_uri(dc, media.url.toStdString().data(), &err2);

        if(info){
            GstDiscovererResult r = gst_discoverer_info_get_result(info);
            if(r==GST_DISCOVERER_OK){
                result = true;
            }
            gst_discoverer_info_unref (info);
        }
        if (err2){
            g_error_free (err2);
        }

        if(dc){
            gst_object_unref (dc);
        }
        if (err){
            g_error_free (err);
        }

        if(m_stopReq){
            break;
        }
        if(result){
            if(containId(media.id)){
                //先移除探测的媒体，再发出信号。否则外部调用containId或containUrl可能会错判
                removeMedia(media.id);

                //延迟一段时间后再发出信号，确保端口占用已被释放
                m_resumeMutex.lock();
                m_resumeCond.wait(&m_resumeMutex,2*1000);
                m_resumeMutex.unlock();

                emit this->playable(media);
            }
        }
    }
}
